# ----------------------------------------------------------------------------
# pytform
# Copyright (c) 2008, Michael Henrique Siegwarth
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions 
# are met:
#
#  * Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#  * Redistributions in binary form must reproduce the above copyright 
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with the
#    distribution.
#  * Neither the name of pytform nor the names of its
#    contributors may be used to endorse or promote products
#    derived from this software without specific prior written
#    permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ----------------------------------------------------------------------------

import os
import sys # exit, argv
import copy

import pyglet
from pyglet.gl import *
from pyglet.window import key
import yaml

import base.app
from base.event import *
from objects import *

class StatusBar(object):
    def __init__(self, screen_size):
        self.screen_size = screen_size
        
        self.print_main()

    def draw(self):
        glPushMatrix()
        glBegin(GL_QUADS)
        glColor3f(0, 0, 0)
        glVertex2f(0, 0)
        glVertex2f(0, 50)
        glVertex2f(self.screen_size[0], 50)
        glVertex2f(self.screen_size[0], 0)
        glEnd()
        glPopMatrix()

        # TODO - Optimize
        pyglet.text.Label(self.status_description, font_name="fonts/GenAI102.ttf",
                          font_size=15, x=10, y=30).draw()

        pyglet.text.Label(self.status_commands, font_name="fonts/GenAI102.ttf",
                          font_size=10, x=10, y=10).draw()

    def print_object_delete_confirm(self):
        self.status_description = "This object is associated with events. Delete the events first."

    def print_main(self):
        self.status_description = "Welcome to the Pytform level editor!"
        self.status_commands = "'q'- Save map   " \
                               "'1'- Terrain Creation   " \
                               "'2'- Terrain/Object Selection   " \
                               "'3'- Texture Edition   " \
                               "'4'- Object Creation   " \
                               "'5'- Event Creation/Edition"
 

    def print_terrain_main(self):
        self.status_description = "Terrain creation mode. Click to create the first vertex."
        self.status_commands = "'i', 'j', 'k' and 'l' to move. 'a' and 's' to zoom in and out"

    def print_select_main(self, selected_object):
        self.status_description = "Click to select an object. "
        if isinstance(selected_object, triangle.TerrainTriangle):
            cv = selected_object.color_vertices
            self.status_commands = "Vertex 1 ->" + \
                " R: " + str(u'%.2f' % cv[0][0]) + \
                " G: " + str(u'%.2f' % cv[0][1]) + \
                " B: " + str(u'%.2f' % cv[0][2]) + \
                "   Vertex 2 ->" + \
                " R: " + str(u'%.2f' % cv[1][0]) + \
                " G: " + str(u'%.2f' % cv[1][1]) + \
                " B: " + str(u'%.2f' % cv[1][2]) + \
                "   Vertex 3 ->" + \
                " R: " + str(u'%.2f' % cv[2][0]) + \
                " G: " + str(u'%.2f' % cv[2][1]) + \
                " B: " + str(u'%.2f' % cv[2][2])
        else:
             self.status_commands = "Not a terrain triangle."   
        
    def print_texture_main(self, selected_object):
        self.status_description = "Click to select an object"
        if isinstance(selected_object, triangle.TerrainTriangle):
            if selected_object.texture != None:
                self.status_commands = "Texture file: " + selected_object.texture.file
            else:
                self.status_commands = "This triangle has no texture."
        else:
            self.status_commands = "This not a terrain triangle."

    def print_object_main(self, selected_object):
        pass

    def print_event_main(self, selected_event):        
        self.status_description = "Event mode. Press 'q' for a new event, or 'e' and 'r' to cycle between existing events."

        if selected_event != None:
            self.status_commands = "   Event function: " + selected_event.name
        else:
            self.status_commands = "There are no events in this level"

    def print_event_creating(self, selected_event, event_name):
        if selected_event.source_object == None:
            self.status_description = "Event mode. Select source object"
        elif selected_event.trigger_object == None:
            self.status_description = "Event mode. Select trigger object"
        else:
            self.status_description = "Event mode. Select event function with 'e' and 'r' and press 'q' to finish."
            self.status_commands = event_name
    
    def print_cant_create_event(self):
        self.status_commands = "You can't create any event because no event method exists in the level's file"

    def print_creating_event_area(self, status):
        if status == 1:
            self.status_description = "Click to start creating the event area."
        elif status == 2:
            self.status_description = "Click on other position to finish the event area."

        self.status_commands = ""

class Modes(object):
    """Modes class. It's just a 'list' of modes"""
    MAIN = "Main"
    TERRAIN = "Terrain"
    SELECT = "Select"
    TEXTURE = "Texture"
    OBJECT = "Object"
    EVENT = "Event"

class LevelEditor(base.app.App):
    "The screen itself"
    def __init__(self, level_name):
        super(LevelEditor, self).__init__()

        # All textures available in the "global" textures folder
        self.textures = []
        self.load_textures()

        # Current level
        mod = "levels." + level_name + "." + level_name
        
        try:
            exec "import " + mod
        except ImportError:
            self.create_new_level(level_name)
            exec "import " + mod
            
        n = mod + "." + level_name.capitalize()
        self.level = eval(n)(self, self.textures)

        # Texture index currently being cycled through
        self.selected_texture_index = 0

        # Current mode
        self.mode = Modes.MAIN

        # Selected object (can be a terrain or normal object)
        # Get the last strip from the loaded level
        if len(self.level.strips) != 0:
            self.selected_object = self.level.strips[-1]
        else:
            self.selected_object = None

        # Selected object vertex (0 means all vertexes)
        self.selected_vertex = 0

        # Objects list (objects possible to place in the level)
        self.objects = []

        # Batch to "draw" objects that could be placed on the map
        self.temp_object_batch = pyglet.graphics.Batch()

        # Object file being read
        m = open("config.yaml", "r")
        self.object_names = yaml.load(m.read())["objects"]
        m.close()

        for o in self.object_names:
            x = eval(o)(-9, -9, 0, self.level.world, self.temp_object_batch)       
            self.objects.append(x)

        # Current index from the object list (for placing objects)
        self.selected_object_index = 0

        # Vertices of an object being built
        # Used with terrain triangles and event areas
        self.new_stored_vertices = [None, None, None]

        # Number of filled vertices for an object being created
        self.vertex_number = 0

        # Default object color
        self.default_color = (0, 0, 0)

        # Is an event area being created?
        self.creating_event_area = False

        # Selected event name index
        self.selected_event_name_index = 0

        # Creating a new event?
        self.creating_new_event = False

        # Selected event
        if self.level.level_events != []:
            self.selected_event = self.level.level_events[0]
        else:
            self.selected_event = None

        # Get event method names
        self.event_names = self.level.get_event_names()

        # Wireframe mode
        self.wireframe = False

        # Status bar
        self.status_bar = StatusBar(self.screen_size)

    def create_new_level(self, level_name):
        # Create level folder
        os.mkdir("levels/" + level_name)
            
        # Create __init__.py
        init = open("levels/" + level_name + "/__init__.py", "w")
        init.write("__all__ = [\"" + level_name + "\"]")
        init.close()

        # Create level stub
        m = open("levels/" + level_name + "/" + level_name + ".yaml", "w")
        m_stub = "world:\n" \
                 "  gravity: [0, -10]\n" \
                 "screen:\n" \
                 "  offset: [0, 0]\n" \
                 "  ppm: 20\n" \
                 "background:\n" \
                 "  bg: []\n" \
                 "  distance: 10\n" \
                 "  offset:\n" \
                 "  - 0\n" \
                 "  - 0\n" \
                 "  size:\n" \
                 "  - 30\n" \
                 "  - 30\n" \
                 "events: []\n" \
                 "objects: []\n" \
                 "player:\n" \
                 "  start_position: [10.0, 10.0, 0.0]\n" \
                 "  class: player_object.PlayerObject\n" \
                 "textures: []\n" \
                 "triangles: [] "

        m.write(m_stub)
        m.close()

        # Create script stub
        s = open("levels/" + level_name + "/" + level_name + ".py", "w")
        s_stub = "\nimport base.level\n\n" + \
                 "class " + level_name.capitalize() + "(base.level.Level):\n" + \
                 "    def __init__(self, app, textures=None):\n" + \
                 "        base.level.Level.__init__(self, \""+ level_name + "\", app, textures)\n"
        s.write(s_stub)
        s.close()

    def load_textures(self):
        """Load all textures found in the textures folder."""
        files = os.listdir("textures")
        for f in files:
            try:
                tex = pyglet.image.load("textures/" + f)
                setattr(tex, "file", f)
                self.textures.append(tex)
            except Exception:
                # Don't append invalid files (maybe there are more
                # than image files in the textures folder)
                pass
   
    def handle_world_draw(self):
        if self.mode == Modes.TERRAIN:
            # Draw triangle currently being built
            self.draw_temp_triangle()
        elif self.mode == Modes.SELECT or self.mode == Modes.TEXTURE:
            self.draw_selected_object_markings()
        elif self.mode == Modes.OBJECT:
            self.move_temp_object()
        elif self.mode == Modes.EVENT:
            self.draw_temp_event_area()
            self.draw_event_object_markings()
            
        self.draw_map_limit()

    def draw_map_limit(self):
        if -self.map_offset[0] < 0:
            glPushMatrix()
            glBegin(GL_QUADS)
            glColor3f(0, 0, 0)
            glVertex2f(-self.map_offset[0], -self.map_offset[1])
            glVertex2f(-self.map_offset[0], -self.map_offset[1] + self.screen_size[1]/self.ppm) 
            glVertex2f(0, -self.map_offset[1] + self.screen_size[1]/self.ppm)
            glVertex2f(0, -self.map_offset[1])
            glEnd()
            glPopMatrix()

        if -self.map_offset[1] < 0:
            glPushMatrix()
            glBegin(GL_QUADS)
            glColor3f(0, 0, 0)
            glVertex2f(0, -self.map_offset[1])
            glVertex2f(0, 0) 
            glVertex2f(-self.map_offset[0] + self.screen_size[0]/self.ppm, 0)
            glVertex2f(-self.map_offset[0] + self.screen_size[0]/self.ppm, -self.map_offset[1])
            glEnd()
            glPopMatrix()

    def handle_normal_draw(self):
        self.status_bar.draw()
        pass

    def handle_mouse_down(self, pos):
        if self.mode == Modes.SELECT or self.mode == Modes.TEXTURE:
            # Handle triangle selection
            self.reset_vertices()
            o = self.level.get_object_in(self.pointer_position)
            if o == None:
                t = self.level.get_triangle_in(self.pointer_position)
                if t != None:
                    self.selected_object = t
            else:
                self.selected_object = o

            if self.mode == Modes.SELECT:
                self.status_bar.print_select_main(self.selected_object)
            else:
                self.status_bar.print_texture_main(self.selected_object)
                
        elif self.mode == Modes.OBJECT:
            i = self.selected_object_index
            o = self.objects[i]

            new_o = eval(self.object_names[i])(o.position[0], o.position[1],
                                               o.angle ,self.level.world,
                                               self.level.object_batch)
            
            new_o.id = self.level.next_id 
            self.level.objects.append(new_o)
            
        elif self.mode == Modes.EVENT:
            if self.creating_new_event == True:
                o = self.level.get_object_in(self.pointer_position)
                if o != None:
                    if self.selected_event.source_object == None:
                        self.selected_event.source_object = o
                        self.status_bar.print_event_creating(self.selected_event,
                                                             self.event_names[self.selected_event_name_index])
                    elif self.selected_event.trigger_object == None:
                        self.selected_event.trigger_object = o
                        self.status_bar.print_event_creating(self.selected_event,
                                                             self.event_names[self.selected_event_name_index])

                        # Also already add the event name (this will make the event complete)
                        self.selected_event.name = \
                            self.event_names[self.selected_event_name_index]
                        self.selected_event.func = \
                            eval("self.level." + self.event_names[self.selected_event_name_index])

    def handle_mouse_up(self, pos):
        if self.mode == Modes.TERRAIN:
            self.add_terrain_vertices(pos)
        elif self.mode == Modes.EVENT:
            self.create_event_area(pos)

    def handle_mouse_drag(self, pos, delta):
        if self.mode == Modes.SELECT:
            try:
                if self.pressed_modifiers & key.MOD_CTRL:
                    self.selected_object.rotate(delta[1] * 10)
                elif self.pressed_modifiers & key.MOD_ALT:
                    if delta[1] > 0:
                        self.selected_object.scale(1.1)
                    else:
                        self.selected_object.scale(0.9)
                else:
                    if self.selected_vertex == 0:
                        self.selected_object.move(delta)
                    else:
                        self.selected_object.move_vertex(self.selected_vertex-1, delta)
            except AttributeError:
                pass
                    
        elif self.mode == Modes.TEXTURE:
            try:
                if self.pressed_modifiers & key.MOD_CTRL:
                    self.selected_object.rotate_texture(delta[1] * 10)
                elif self.pressed_modifiers & key.MOD_ALT:
                    if delta[1] > 0:
                        self.selected_object.scale_texture(1.1)
                    else:
                        self.selected_object.scale_texture(0.9)
                else:
                    if self.selected_vertex == 0:
                        self.selected_object.move_texture_vertices(delta)
                    else:
                        self.selected_object.move_texture_vertex(self.selected_vertex-1, delta)
            except AttributeError:
                pass
        else:
            if self.pressed_modifiers & key.MOD_ALT:
                # Level zoom
                if delta[1] > 0:
                    self.map_zoom_in(1.1)
                else:
                    self.map_zoom_out(0.9)
            else:    
                # Moves the level with mouse dragging
                self.map_offset[0] += delta[0]
                self.map_offset[1] += delta[1]

    def handle_key_press(self, symbol):
        if self.mode == Modes.SELECT:
            if symbol == key.V:
                # Change vertex selection
                self.change_vertex_selection()
            elif symbol == key.D:
                try:
                    # Test for color_vertices existance (TerrainTriangle)
                    self.selected_object.color_vertices
                    # Delete selected triangle
                    self.selected_object = self.level.remove_triangle(self.selected_object)
                except AttributeError:
                    # If the object is destroyed, remove all its vertices in
                    # the video memory
                    if self.level.get_events_from_object(self.selected_object) == None:
                        self.selected_object = self.level.remove_object(self.selected_object)
                    else:
                        # TODO - Make force option here
                        self.status_bar.print_object_delete_confirm()

        elif self.mode == Modes.TEXTURE:
            if symbol == key.LEFT:
                # Cycle through loaded textures
                self.select_previous_texture()
                self.status_bar.print_texture_main(self.selected_object)
            elif symbol == key.RIGHT:
                # Cycle through loaded textures
                self.select_next_texture()
                self.status_bar.print_texture_main(self.selected_object)
            elif symbol == key.V:
                self.change_vertex_selection()
            elif symbol == key.D:
                self.selected_object.set_texture(None, self.level.terrain_batch)
                self.status_bar.print_texture_main(self.selected_object)
                
        elif self.mode == Modes.OBJECT:
            if symbol == key.LEFT:
                self.select_previous_object()
            elif symbol == key.RIGHT:
                self.select_next_object()
                
        elif self.mode == Modes.EVENT:
            if symbol == key.LEFT:            
                self.select_previous_event()

                if self.creating_new_event == False:
                    self.status_bar.print_event_main(self.selected_event)
                else:
                    self.status_bar.print_event_creating(self.selected_event,
                                                         self.event_names[self.selected_event_name_index])    
            elif symbol == key.RIGHT:           
                self.select_next_event()
                
                if self.creating_new_event == False:
                    self.status_bar.print_event_main(self.selected_event)
                else:
                    self.status_bar.print_event_creating(self.selected_event,
                                                         self.event_names[self.selected_event_name_index])
            elif symbol == key.D:
                # Delete the selected event
                if self.creating_new_event == False:
                    if self.selected_event != None:
                        self.level.remove_event(self.selected_event)

                        self.select_previous_event()
                        self.status_bar.print_event_main(self.selected_event)       
            elif symbol == key.W:
                self.creating_event_area = True
                self.status_bar.print_creating_event_area(1)
            elif symbol == key.Q:
                if self.event_names == []:
                    self.status_bar.print_cant_create_event()
                else:
                    # Create an empty event, which will be filled with data later
                    if self.creating_new_event == False:
                        self.creating_new_event = True
                        self.selected_event = LevelEvent(None, None, None, "a", None)
                        
                        self.status_bar.print_event_creating(self.selected_event,
                                                             self.event_names[self.selected_event_name_index])
                    else:
                        self.creating_new_event = False

                        if self.selected_event.source_object == None or \
                           self.selected_event.trigger_object == None:
                            self.level.remove_event(self.selected_event)
                            self.select_previous_event()
                        else:
                            self.level.add_event(self.selected_event)
                        
                        self.status_bar.print_event_main(self.selected_event)
            elif symbol == key.A:
                if self.creating_new_event == True:
                    self.selected_event.event_type = "a"
                    self.status_bar.print_event_creating(self.selected_event,
                                                         self.event_names[self.selected_event_name_index])

            elif symbol == key.R:
                if self.creating_new_event == True:
                    self.selected_event.event_type = "r"
                    self.status_bar.print_event_creating(self.selected_event,
                                                         self.event_names[self.selected_event_name_index])
                    
        elif self.mode == Modes.MAIN:
            if symbol == key.W:
                self.wireframe = not self.wireframe
                self.wireframe_mode(self.wireframe)
            elif symbol == key.Q:
                self.level.save()
            elif symbol == key.ESCAPE:
                # TODO - Quit more gracefully
                sys.exit(1)
                
        # Modes
        if symbol == key._1:
            self.status_bar.print_terrain_main()
            self.mode = Modes.TERRAIN
        elif symbol == key._2:
            self.status_bar.print_select_main(self.selected_object)
            self.reset_vertices() 
            self.mode = Modes.SELECT
        elif symbol == key._3:
            self.status_bar.print_texture_main(self.selected_object)
            self.reset_vertices()
            self.mode = Modes.TEXTURE
        elif symbol == key._4:
            self.status_bar.print_object_main(self.selected_object)
            self.reset_vertices()            
            self.mode = Modes.OBJECT
        elif symbol == key._5:
            self.status_bar.print_event_main(self.selected_event)
            self.reset_vertices()
            self.mode = Modes.EVENT
        elif symbol == key.ESCAPE:
            # Quit all modes
            self.status_bar.print_main()
            self.mode = Modes.MAIN

    def handle_key_down(self):
        value = 1
        modified = 10

        if self.pressed_modifiers & key.MOD_SHIFT:
            value = modified

        if self.pressed_modifiers & key.MOD_CTRL:
            value = value * -1

        if self.mode == Modes.SELECT and self.selected_object != None:
            try:
                # Object colors    
                if self.keys[key.R]:            
                    self.paint_object(0, value)
                    self.status_bar.print_select_main(self.selected_object)
                elif self.keys[key.G]:            
                    self.paint_object(1, value)
                    self.status_bar.print_select_main(self.selected_object)
                elif self.keys[key.B]:
                    self.paint_object(2, value)
                    self.status_bar.print_select_main(self.selected_object)
            except AttributeError:
                pass

    def add_terrain_vertices(self, pos):
        self.new_stored_vertices[self.vertex_number] = [pos[0]/self.ppm - self.map_offset[0],
                                                        pos[1]/self.ppm - self.map_offset[1]]        
        self.vertex_number += 1

        if self.vertex_number == 1:
            self.status_description = "Terrain creation mode. Click to create the second vertex."
        elif self.vertex_number == 2:     
            self.status_description = "Terrain creation mode. Click to create the third vertex."
        elif self.vertex_number == 3:
            self.status_description = "Terrain creation mode. Click to create the first vertex."
            if isinstance(self.selected_object, triangle.TerrainTriangle):
                color = list(self.selected_object.vertex_list[0].colors)
                tv = list(self.selected_object.vertex_list[0].tex_coords)
                texture = self.selected_object.texture
            else:
                color = list(self.default_color * 3)
                tv = [0, 0, 0, 1.0, 1.0, 0]
                texture = None

            self.selected_object = self.level.create_triangle(
                self.new_stored_vertices,
                tv, color, texture)

            self.reset_vertices()

    def create_event_area(self, pos):
        if self.creating_event_area == True:
            self.new_stored_vertices[self.vertex_number] = [pos[0]/self.ppm - self.map_offset[0],
                                                            pos[1]/self.ppm - self.map_offset[1]]
            self.vertex_number += 1

            self.status_bar.print_creating_event_area(2)

            if self.vertex_number == 2:
                self.creating_event_area = False
                x = (self.new_stored_vertices[0][0] + self.new_stored_vertices[1][0]) / 2
                y = (self.new_stored_vertices[0][1] + self.new_stored_vertices[1][1]) / 2
                dim_x = self.new_stored_vertices[0][0] - self.pointer_position[0]
                if dim_x < 0:
                    dim_x *= -1

                dim_y = self.new_stored_vertices[0][1] - self.pointer_position[1]
                if dim_y < 0:
                    dim_y *= -1

                ea = quad.EventArea(x, y, 0, dim_x, dim_y,
                                    self.level.world, self.level.object_batch)
                ea.id = self.level.next_id
                self.level.objects.append(ea)
                
                self.reset_vertices()

                self.status_bar.print_event_main(self.selected_event)

    def select_previous_texture(self):
        self.selected_texture_index -= 1

        if self.selected_texture_index == -1:
            self.selected_texture_index = len(self.textures) - 1

        if self.selected_object.texture != None:
            self.selected_object.set_texture(self.textures[self.selected_texture_index], self.level.terrain_batch)
        else:
            self.selected_object.set_texture(self.textures[0], self.level.terrain_batch)
            
        self.selected_object.texture_id = self.selected_object.texture.get_texture().id            

    def select_next_texture(self):

        self.selected_texture_index += 1

        if self.selected_texture_index == len(self.textures):
            self.selected_texture_index = 0

        if self.selected_object.texture != None:
            self.selected_object.set_texture(self.textures[self.selected_texture_index], self.level.terrain_batch)
        else:
            self.selected_object.set_texture(self.textures[0], self.level.terrain_batch)

        self.selected_object.texture_id = self.selected_object.texture.get_texture().id

    def select_previous_event(self):
        if self.creating_new_event == False:
            if self.selected_event != None:
                for index, item in enumerate(self.level.level_events):
                    if item == self.selected_event:
                        if index - 1 != -1:
                            self.selected_event = self.level.level_events[index - 1]
                        else:
                            self.selected_event = self.level.level_events[len(self.level.level_events) - 1]

                        break     
               
        else:
            # Creating a new event. Pick one of them from the list
            if self.event_names != []:
                self.selected_event_name_index -= 1
            
                if self.selected_event_name_index == -1:
                    self.selected_event_name_index = len(self.event_names) - 1

                self.selected_event.name = \
                    self.event_names[self.selected_event_name_index]
                self.selected_event.func = \
                    eval("self.level." + self.event_names[self.selected_event_name_index])

    def select_next_event(self):
        if self.creating_new_event == False:
            if self.selected_event != None:
                for index, item in enumerate(self.level.level_events):
                    if item == self.selected_event:
                        if index + 1 != len(self.level.level_events):
                            self.selected_event = self.level.level_events[index + 1]
                        else:
                            self.selected_event = self.level.level_events[0]

                        break  
        else:
            # Creating a new event. Pick one of them from the list
            if self.event_names != []:
                self.selected_event_name_index += 1

                if self.selected_event_name_index == len(self.event_names):
                    self.selected_event_name_index = 0

                self.selected_event.name = \
                    self.event_names[self.selected_event_name_index]
                self.selected_event.func = \
                    eval("self.level." + self.event_names[self.selected_event_name_index])
            else:
                self.status_bar.print_cant_create_event()

    def change_vertex_selection(self):
        """ Change vertex selection """
        if isinstance(self.selected_object, triangle.TerrainTriangle):
            self.selected_vertex += 1
            if self.selected_vertex == 4:
                self.selected_vertex = 0

    def paint_object(self, color, value):
        if self.selected_vertex == 0:
            self.selected_object.paint(color, value)
        else:
            self.selected_object.paint_vertex(self.selected_vertex-1, color, value)

    def map_zoom_in(self, value):
        old_ppm = self.ppm
        self.ppm += value
        self.map_offset[0] += ((self.screen_size[0]/self.ppm) -
                               (self.screen_size[0]/old_ppm))/2
        self.map_offset[1] += ((self.screen_size[1]/self.ppm) -
                               (self.screen_size[1]/old_ppm))/2

    def map_zoom_out(self, value):
        if self.ppm - value > 0:
            old_ppm = self.ppm
            self.ppm -= value
            self.map_offset[0] -= ((self.screen_size[0]/old_ppm) -
                                   (self.screen_size[0]/self.ppm))/2
            self.map_offset[1] -= ((self.screen_size[1]/old_ppm) -
                                   (self.screen_size[1]/self.ppm))/2

    def select_previous_object(self):
        self.objects[self.selected_object_index].position = (-9, -9)
        self.objects[self.selected_object_index].update_vertices()
        
        self.selected_object_index -= 1
        
        if self.selected_object_index == -1:
            self.selected_object_index = len(self.objects) - 1

    def select_next_object(self):
        self.objects[self.selected_object_index].position = (-9, -9)
        self.objects[self.selected_object_index].update_vertices()

        self.selected_object_index += 1
                
        if self.selected_object_index == len(self.objects):
            self.selected_object_index = 0

    def draw_temp_triangle(self):
        """Draw triangle currently being built"""
        if self.new_stored_vertices[2] == None:
            if isinstance(self.selected_object, triangle.TerrainTriangle):
                color = list(self.selected_object.vertex_list[0].colors)
                tv = list(self.selected_object.vertex_list[0].tex_coords)
                texture = self.selected_object.texture
            else:
                color = list(self.default_color * 3)
                tv = [0, 0, 0, 1.0, 1.0, 0]
                texture = None

            if self.new_stored_vertices[1] == None:
                if self.new_stored_vertices[0] != None:
                    # One vertex was already filled, so draw a line
                    glBegin(GL_LINES)
                    glColor3f(color[0], color[1], color[2]) 
                    glVertex2f(self.new_stored_vertices[0][0],
                               self.new_stored_vertices[0][1])
                    glColor3f(color[3], color[4], color[5])
                    glVertex2f(self.pointer_position[0],
                               self.pointer_position[1])
                    glEnd()
            else:
                # Two vertices filled, draw a triangle
                t = pyglet.graphics.vertex_list(3,
                    ('v2f', (self.new_stored_vertices[0][0],
                             self.new_stored_vertices[0][1],
                             self.new_stored_vertices[1][0],
                             self.new_stored_vertices[1][1],
                             self.pointer_position[0],
                             self.pointer_position[1])),
                    'c3f', 't2f'
                )
                
                t.colors = color
                t.tex_coords = tv

                if texture != None:
                    glEnable(GL_TEXTURE_2D)
                    glBindTexture(GL_TEXTURE_2D, texture.get_texture().id)
                t.draw(pyglet.gl.GL_TRIANGLES)
                glDisable(GL_TEXTURE_2D)

    def draw_temp_event_area(self):
        if self.new_stored_vertices[0] != None:
            glBegin(GL_QUADS)
            glColor4f(1, 1, 1, 0.5)
            glVertex2f(self.new_stored_vertices[0][0],
                       self.new_stored_vertices[0][1])
            glVertex2f(self.new_stored_vertices[0][0],
                       self.pointer_position[1])
            glVertex2f(self.pointer_position[0],
                       self.pointer_position[1])
            glVertex2f(self.pointer_position[0],
                       self.new_stored_vertices[0][1])
            glEnd()

    def draw_selected_object_markings(self):
        self.draw_markings(self.selected_object)

    def draw_markings(self, obj):
        # Make the markings black
        glColor4f(0, 0, 0, 1)

        if obj != None:
            if self.selected_vertex == 0 or not isinstance(obj, triangle.TerrainTriangle):
                vertices = obj.vertices
                
                for v in vertices:
                    self.draw_marking(v)
            else:
                v = obj.vertices[self.selected_vertex - 1]
                self.draw_marking(v)

    def draw_marking(self, v):
        cons = 0.1
        glBegin(GL_QUADS)
        glVertex2f(v[0] - cons, v[1] - cons)
        glVertex2f(v[0] + cons, v[1] - cons)
        glVertex2f(v[0] + cons, v[1] + cons)
        glVertex2f(v[0] - cons, v[1] + cons)
        glEnd()

    def draw_event_object_markings(self):
        if self.selected_event != None:
            s = self.selected_event.source_object
            t = self.selected_event.trigger_object

            self.draw_markings(s)
            self.draw_markings(t)

    def reset_vertices(self):
        self.new_stored_vertices = [None, None, None]
        self.vertex_number = 0
    
    def move_temp_object(self):
        # Draw object on the mouse position
        o = self.objects[self.selected_object_index]
        o.position = tuple(self.pointer_position)
        o.update_vertices()
        self.temp_object_batch.draw()

    def game_step(self, dt):
        self.handle_key_down()

def main():
    if len(sys.argv) > 1:
        editor = LevelEditor(sys.argv[1])
        editor.loop()
    else:
        print "This program needs an argument, which is the level name."
        print "-> If the level already exists, it will be loaded."
        print "-> If the level doesn't exist, a new one will be created."

if __name__ == "__main__":
    main()
